package com.game;

import java.util.ArrayList;
import java.util.Random;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.Log;

public class PuzzlePathManager {
	
	private static final String TAG = PuzzlePathManager.class.getSimpleName();
	private static final int PATH_ROTATE_MAX = 4;
	
	private Random random = null;
	
	private PuzzleTemplatePath TemplatePath = null;
	private ArrayList<PuzzleUtil> pathList = null;
	private PuzzleUtil focusUtil = null;
	private int[] layer = null;
	private int[] rotateTimes = null;
	
	private RectF drawArea = null;
	
	public PuzzlePathManager() {
		pathList = new ArrayList<PuzzleUtil>();
		random = new Random();
	}
	
	public void createTemplatePath(float x, float y, float width, float height, int row, int coloum) {
		if (TemplatePath == null) {
			TemplatePath = new PuzzleTemplatePath();
		}
		TemplatePath.setStartPos(x, y);
		TemplatePath.setWH(width, height);
		TemplatePath.setCL(row, coloum);
		TemplatePath.setRandomUtil();
		
		drawArea = new RectF(x, y, x + width, y + height);
	}
	
	public void clearTemplatePath() {
		TemplatePath.clear();
	}
	
	private void rotatePathState(PuzzleUtil _util, int rotateTimes) {
		//默认顺时针旋转 
		int tempState = 0;
		
		int leftState = _util.getLeftState();;
		int rightState = _util.getRightState();
		int topState = _util.getTopState();
		int bottomState = _util.getBottomState();

		for (int i = 0; i < rotateTimes; i++) {
			tempState = leftState;
			leftState = bottomState;
			bottomState = rightState;
			rightState = topState;
			topState = tempState;
			
		}
		
		_util.setEdgeState(leftState, topState, rightState, bottomState);
	}
	
	public boolean createPathList(PuzzlePathArea area, boolean rotate) {
		int randX = 0, randY = 0;
		if (TemplatePath == null) {
			return false;
		}
		
		ArrayList<PuzzleUtil> _utilArray = TemplatePath.getPuzzleUtilList();
		layer = new int[_utilArray.size()];
		
		//初始化旋转状态
		rotateTimes = new int[_utilArray.size()];
		for (int i = 0; i < rotateTimes.length; i++) {
			if (rotate) {
				rotateTimes[i] = random.nextInt(PATH_ROTATE_MAX);
			}
			else {
				rotateTimes[i] = 0;
			}
			System.out.println("rotateTimes[" + i + "]" + ":" + rotateTimes[i]);
		}
		
		for (int i = 0; i < _utilArray.size(); i++) {
			PuzzleUtil _util = _utilArray.get(i).copyUtil();
			
			if (rotate) {
				rotatePathState(_util, rotateTimes[i]);
			}
			
			if (area != null) {
				Log.v(TAG, "area width " + area.getAreaWidth() + "templatePath width " + TemplatePath.getPathWidth());
				randX = random.nextInt((int)(area.getAreaWidth() - TemplatePath.getPathWidth())) + (int)area.getLeftEdge();
				//Log.v(TAG, "LeftEdge " + area.getLeftEdge());
				//Log.v(TAG, "randX " + randX);
				randY = random.nextInt((int)(area.getAreaHeight() - TemplatePath.getPathHeight())) + (int)area.getTopEdge();
				//Log.v(TAG, "TopEdge " + area.getTopEdge());
				//Log.v(TAG, "randY " + randY);
			}
			_util.setEdge(randX, randY, 
					 	  randX + TemplatePath.getPathWidth(),
					      randY + TemplatePath.getPathHeight());	
			
			pathList.add(_util);
			setLayer(_util, i);
		}
		
		return true;
	}
	
	public void clearPathList() {
		pathList.clear();
	}
	
	private boolean areaImpact(float left1, float top1, float right1, float bottom1,
			                  float left2, float top2, float right2, float bottom2) {
		if ((right1 < left2) || (left1 > right2) ||
		   (bottom1 < top2) || (top1 > bottom2)) {
			return false;
		}
		return true;
	}
	
	private void setLayer(PuzzleUtil _util, int index) {
		PuzzleUtil tmpUtil = null;
		layer[index] = 0;
		for (int i = 0; i < index; i++) {
			tmpUtil = pathList.get(i);
			if (areaImpact(_util.getLeft(), _util.getTop(), _util.getRight(), _util.getBottom(),
					       tmpUtil.getLeft(), tmpUtil.getTop(), tmpUtil.getRight(), tmpUtil.getBottom())) {
				if (layer[index] <= layer[i]) {
					layer[index] = layer[i] + 1;
				}
			}
		}
	}
	
	public float getTgetTemplatePathTop() {
		if (TemplatePath != null) {
			return TemplatePath.getPathTop();
		}
		else {
			return 0;
		}
	}
	
	public float getTgetTemplatePathLeft() {
		if (TemplatePath != null) {
			return TemplatePath.getPathLeft();
		}
		else {
			return 0;
		}
	}
	
	public float getTemplatePathWidth() {
		if (TemplatePath != null) {
			return TemplatePath.getPathWidth();
		}
		else {
			return 0;
		}
	}
	
	public float getTemplatePathHeight() {
		if (TemplatePath != null) {
			return TemplatePath.getPathHeight();
		}
		else {
			return 0;
		}
	}
	
	public ArrayList<PuzzleUtil> getPathList() {
		return pathList;
	}
	
	private int getLayer(int index) {
		if (index > layer.length) {
			return -1;
		}
		else
			return layer[index];
	}
	
	private int getMaxLayer() {
		int maxLayer = 0;
		for (int i = 0; i < layer.length; i++) {
			if (layer[i] > maxLayer) {
				maxLayer = layer[i];
			}
		}
		return maxLayer;
	}
	
	private void modifyLayer(int needModifyLayer) {
		for (int i = 0; i < layer.length; i++) {
			if (layer[i] == needModifyLayer) {
				return ;
			}
		}
		for (int i = 0; i < layer.length; i++) {
			if (layer[i] > needModifyLayer) {
				layer[i]--;
			}
		}
	}
	
	public void cleanFocusUtil() {
		focusUtil = null;
	}
	
	public PuzzleUtil getFocusUtil(float x, float y) {
		int maxLayerIndex = -1;	//用于记录存于最上层的index
		
		for (int i = 0; i < pathList.size(); i++) {
			PuzzleUtil tmpUtil = pathList.get(i); 
			if (tmpUtil.getLeft() < x && x < tmpUtil.getRight() &&
				tmpUtil.getTop() < y && y < tmpUtil.getBottom()) {
				if (maxLayerIndex == -1 || layer[i] > layer[maxLayerIndex]) {
					maxLayerIndex = i;
				}
			}
		}
		if (maxLayerIndex == -1) {
			focusUtil = null;
		}
		else {
			
			int maxLayer = getMaxLayer();
			int needModifyLayer = layer[maxLayerIndex];
			layer[maxLayerIndex] = maxLayer + 1;
			modifyLayer(needModifyLayer);
			focusUtil = pathList.get(maxLayerIndex);
		}
		
		return focusUtil;
	}
	
	public void printLayer() {
		for (int i = 0; i < layer.length; i++) {
			Log.v(TAG, "layer[" + i + "]" + " " + layer[i]);
		}
	}
	
	private PuzzleUtil getNearestUtil(float offset) {
		if (focusUtil == null ||
			TemplatePath == null) {
			return null;
		}
		PuzzleUtil nearestUtil = null;
		for (int i = 0; i < TemplatePath.size(); i++) {
			nearestUtil = TemplatePath.get(i);
			if ((nearestUtil != null) &&
				(Math.abs(focusUtil.getLeft() - nearestUtil.getLeft()) < offset) && 
				(Math.abs(focusUtil.getTop() - nearestUtil.getTop()) < offset)) {
				return nearestUtil;
			}
		}
		return null;
	}
	
	public void autoAttach(float offset) {
		if (focusUtil != null) {
			PuzzleUtil nearestUtil = getNearestUtil(offset); 
			if (nearestUtil != null) {
				focusUtil.setOffset(nearestUtil.getLeft() - focusUtil.getLeft(),
									nearestUtil.getTop() - focusUtil.getTop());
			}
		}
	}
	
	public void rotateFocusPath() {
		int i = 0;
		if (focusUtil != null) {
			for (i = 0; i < pathList.size(); i++) {
				if (pathList.get(i) == focusUtil) {
					break;
				}
			}
			rotateTimes[i] = (rotateTimes[i] + 1) % PATH_ROTATE_MAX;
			rotatePathState(focusUtil, 1);
			focusUtil.initPath();
		}
	}
	
	public  boolean puzzleComplete(float offset) {
		
		if (TemplatePath == null || pathList == null) {
			return false;
		}
		ArrayList<PuzzleUtil> templateList = TemplatePath.getPuzzleUtilList();
		for (int i = 0; i < templateList.size(); i++) {
			if ((Math.abs(templateList.get(i).getLeft() - pathList.get(i).getLeft()) > offset) ||
				(Math.abs(templateList.get(i).getTop() - pathList.get(i).getTop()) > offset)) {
				return false;
			}
		}
		return true;
	}
	
//	public static int getNearestUtilIndex(PuzzleUtil _util) {
//		
//	}

	public void drawTemplatePath(Bitmap bmp, Canvas canvas, Paint paint) {
		if (TemplatePath != null) {
			ArrayList<PuzzleUtil> templateList = TemplatePath.getPuzzleUtilList();
			for (int i = 0; i < templateList.size(); i++) {
				canvas.save();
				canvas.clipPath(templateList.get(i).getPath());
				drawArea.set(templateList.get(i).getLeft() - TemplatePath.getOffsetLeft(i), 
						     templateList.get(i).getTop() - TemplatePath.getOffsetTop(i), 
						     templateList.get(i).getLeft() - TemplatePath.getOffsetLeft(i) + TemplatePath.getTemplateWidth(), 
						     templateList.get(i).getTop() - TemplatePath.getOffsetTop(i) + TemplatePath.getTemplateHeight());
				
				Log.v(TAG, "drawArea Template (" + drawArea.left + "," + drawArea.top + "," 
				                        + drawArea.right + "," + drawArea.bottom + ")");
				canvas.drawBitmap(bmp, null, drawArea, paint);
				canvas.restore();
				canvas.drawPath(templateList.get(i).getPath(), paint);
			}
		}
	}
	
	public void drawPath(Bitmap bmp, Canvas canvas, Paint paint, boolean drawPath) {
		boolean correctPos = false;
		if (pathList != null) {
			paint.setColor(Color.RED);
			for (int i = 0; i <= getMaxLayer(); i++) {
				for (int j = 0; j < pathList.size(); j++) {
					if (i ==  getLayer(j)) {
						//Log.v(TAG, "cur layer " + i + " cur util index " + j);
						if (pathList.get(j) == focusUtil) {
							paint.setARGB(0xEF,0xFF,0xFF,0x0);
						}
						else if ((Math.abs(pathList.get(j).getLeft() - TemplatePath.get(j).getLeft()) < 0.5f) && 
							 	(Math.abs(pathList.get(j).getTop() - TemplatePath.get(j).getTop()) < 0.5f) ){
							correctPos = true;
							paint.setColor(Color.MAGENTA);
						}
						canvas.save();
						canvas.clipPath(pathList.get(j).getPath());
						//Log.v(TAG, "rotateTimes[" +  + "]" + "in draw:" + rotateTimes[i]);
						canvas.rotate(90 * rotateTimes[j], 
								pathList.get(j).getLeft() + (pathList.get(j).getRight() - pathList.get(j).getLeft()) / 2,
								pathList.get(j).getTop() + (pathList.get(j).getBottom() - pathList.get(j).getTop()) / 2);
						drawArea.set(pathList.get(j).getLeft() - TemplatePath.getOffsetLeft(j), 
									 pathList.get(j).getTop() - TemplatePath.getOffsetTop(j), 
									 pathList.get(j).getLeft() - TemplatePath.getOffsetLeft(j) + TemplatePath.getTemplateWidth(), 
									 pathList.get(j).getTop() - TemplatePath.getOffsetTop(j) + TemplatePath.getTemplateHeight());
						Log.v(TAG, "drawArea Path (" + drawArea.left + "," + drawArea.top + "," 
		                        + drawArea.right + "," + drawArea.bottom + ")");
						
						canvas.drawBitmap(bmp,  null, drawArea, paint);
						canvas.restore();
						if (drawPath) {
							canvas.drawPath(pathList.get(j).getPath(), paint);
						}
					
						if (correctPos) {
							correctPos = false;
							paint.setColor(Color.RED);
						}
					}
				}
			}
		}
	}
}
